#include <stdio.h>
#include <string.h>

/* plus function machine code, intel instrucation, can run */
unsigned char machine_code[] = 
{
    0xf3, 0x0f, 0x1e, 0xfa,
    0x55, 
    0x48, 0x89, 0xe5, 
    0x89, 0x7d, 0xfc, 
    0x89, 0x75, 0xf8, 
    0x8b, 0x55, 0xfc,
    0x8b, 0x45, 0xf8,
    0x01, 0xd0,
    0x5d,
    0xc3,
};

/*
0000000000001149 <plus>:
    1149:	f3 0f 1e fa          	endbr64 
    114d:	55                   	push   %rbp
    114e:	48 89 e5             	mov    %rsp,%rbp
    1151:	89 7d fc             	mov    %edi,-0x4(%rbp)
    1154:	89 75 f8             	mov    %esi,-0x8(%rbp)
    1157:	8b 55 fc             	mov    -0x4(%rbp),%edx
    115a:	8b 45 f8             	mov    -0x8(%rbp),%eax
    115d:	01 d0                	add    %edx,%eax
    115f:	5d                   	pop    %rbp
    1160:	c3                   	retq   
*/
int plus(int x, int y) 
{
    return x + y;
}

typedef int (*pfunction)(int x, int y);

int main(int argc, char ** argv)
{
    int m = 0;
    int z = plus(1, 2);
    printf("%d\n", z);

    pfunction p = (pfunction)plus;
    m = p(4,5);
    printf("%d\n", m);

    printf("%p\n", machine_code);     /* output address, debug */
    p = (pfunction)&machine_code;
    printf("%x\n", p(4,5));

    return 0;
}

#if 0
/*
 * intel
 */
0000000000001149 <plus>:
    1149:	f3 0f 1e fa          	endbr64 
    114d:	55                   	push   %rbp
    114e:	48 89 e5             	mov    %rsp,%rbp
    1151:	89 7d fc             	mov    %edi,-0x4(%rbp)  // x
    1154:	89 75 f8             	mov    %esi,-0x8(%rbp)  // y
    1157:	8b 55 fc             	mov    -0x4(%rbp),%edx  // edx=x
    115a:	8b 45 f8             	mov    -0x8(%rbp),%eax  // eax=y
    115d:	01 d0                	add    %edx,%eax        // eax=x+y
    115f:	5d                   	pop    %rbp
    1160:	c3                   	retq   

0000000000001161 <main>:
    1161:	f3 0f 1e fa          	endbr64 
    1165:	55                   	push   %rbp
    1166:	48 89 e5             	mov    %rsp,%rbp
    1169:	48 83 ec 20          	sub    $0x20,%rsp
    116d:	89 7d ec             	mov    %edi,-0x14(%rbp) // (rbp-0x14)=argc
    1170:	48 89 75 e0          	mov    %rsi,-0x20(%rbp) // (rbp-0x20)=argv
    1174:	c7 45 f0 00 00 00 00 	movl   $0x0,-0x10(%rbp) // (rbp-0x10)=0
    117b:	be 02 00 00 00       	mov    $0x2,%esi        // esi=2
    1180:	bf 01 00 00 00       	mov    $0x1,%edi        // edi=1
    1185:	e8 bf ff ff ff       	callq  1149 <plus>      // plus(1, 2)
    118a:	89 45 f4             	mov    %eax,-0xc(%rbp)  // (rbp-0xc)=plus(1,2)
    118d:	8b 45 f4             	mov    -0xc(%rbp),%eax  // eax=plus(1,2)
    1190:	89 c6                	mov    %eax,%esi        // esi=eax
    1192:	48 8d 3d 6b 0e 00 00 	lea    0xe6b(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>  // rdi="%d\n"
    1199:	b8 00 00 00 00       	mov    $0x0,%eax
    119e:	e8 ad fe ff ff       	callq  1050 <printf@plt>    // printf(rdi, esi)
    11a3:	48 8d 05 9f ff ff ff 	lea    -0x61(%rip),%rax        # 1149 <plus>    // rax=plus's address=0x1149
    11aa:	48 89 45 f8          	mov    %rax,-0x8(%rbp)      // rbp-0x8=0x7fffffffe2c8: 0x1149,  (rbp-0x8)=0x1149
    11ae:	48 8b 45 f8          	mov    -0x8(%rbp),%rax      // rax=0x1149
    11b2:	be 05 00 00 00       	mov    $0x5,%esi            // esi=5
    11b7:	bf 04 00 00 00       	mov    $0x4,%edi            // edi=4
    11bc:	ff d0                	callq  *%rax                // rax=0x1149(4, 5), *为过程调用
    11be:	89 45 f0             	mov    %eax,-0x10(%rbp)     // (rbp-0x10)=plus(4,5)
    11c1:	8b 45 f0             	mov    -0x10(%rbp),%eax     // eax=(rbp-0x10)
    11c4:	89 c6                	mov    %eax,%esi            // esi=eax
    11c6:	48 8d 3d 37 0e 00 00 	lea    0xe37(%rip),%rdi        # 2004 <_IO_stdin_used+0x4>  // rdi="%d\n"
    11cd:	b8 00 00 00 00       	mov    $0x0,%eax
    11d2:	e8 79 fe ff ff       	callq  1050 <printf@plt>    // printf(rdi, esi)
    11d7:	48 8d 35 32 2e 00 00 	lea    0x2e32(%rip),%rsi        # 4010 <machine_code>       // rsi=0x4010
    11de:	48 8d 3d 23 0e 00 00 	lea    0xe23(%rip),%rdi        # 2008 <_IO_stdin_used+0x8>  // rdi="%p\n"
    11e5:	b8 00 00 00 00       	mov    $0x0,%eax
    11ea:	e8 61 fe ff ff       	callq  1050 <printf@plt>    // printf(rdi, rsi)
    11ef:	48 8d 05 1a 2e 00 00 	lea    0x2e1a(%rip),%rax        # 4010 <machine_code>       // rax=0x4010
    11f6:	48 89 45 f8          	mov    %rax,-0x8(%rbp)      // (rbp-0x8)=0x4010
    11fa:	48 8b 45 f8          	mov    -0x8(%rbp),%rax      // rax=0x4010
    11fe:	be 05 00 00 00       	mov    $0x5,%esi            // esi=5
    1203:	bf 04 00 00 00       	mov    $0x4,%edi            // edi=4
    1208:	ff d0                	callq  *%rax                // rax=0x4010(4, 5)
    120a:	89 c6                	mov    %eax,%esi
    120c:	48 8d 3d f9 0d 00 00 	lea    0xdf9(%rip),%rdi        # 200c <_IO_stdin_used+0xc>
    1213:	b8 00 00 00 00       	mov    $0x0,%eax
    1218:	e8 33 fe ff ff       	callq  1050 <printf@plt>
    121d:	b8 00 00 00 00       	mov    $0x0,%eax
    1222:	c9                   	leaveq 
    1223:	c3                   	retq   
    1224:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
    122b:	00 00 00 
    122e:	66 90                	xchg   %ax,%ax

/*
 * arm
 */
000000000040055c <plus>:
  40055c:	d10043ff 	sub	sp, sp, #0x10
  400560:	b9000fe0 	str	w0, [sp, #12]   // w0=1
  400564:	b9000be1 	str	w1, [sp, #8]    // w1=2
  400568:	b9400fe1 	ldr	w1, [sp, #12]
  40056c:	b9400be0 	ldr	w0, [sp, #8]
  400570:	0b000020 	add	w0, w1, w0      // w0=w0+w1
  400574:	910043ff 	add	sp, sp, #0x10
  400578:	d65f03c0 	ret

000000000040057c <main>:
  40057c:	a9bd7bfd 	stp	x29, x30, [sp, #-48]!
  400580:	910003fd 	mov	x29, sp
  400584:	b9001fa0 	str	w0, [x29, #28]
  400588:	f9000ba1 	str	x1, [x29, #16]
  40058c:	b9002fbf 	str	wzr, [x29, #44]
  400590:	52800041 	mov	w1, #0x2                   	// #2
  400594:	52800020 	mov	w0, #0x1                   	// #1
  400598:	97fffff1 	bl	40055c <plus>
  40059c:	b9002ba0 	str	w0, [x29, #40]      // [x29+40]=plus(1,2)
  4005a0:	90000000 	adrp	x0, 400000 <_init-0x3e8>
  4005a4:	911b8000 	add	x0, x0, #0x6e0
  4005a8:	b9402ba1 	ldr	w1, [x29, #40]
  4005ac:	97ffffa9 	bl	400450 <printf@plt> // printf
  4005b0:	90000000 	adrp	x0, 400000 <_init-0x3e8>
  4005b4:	91157000 	add	x0, x0, #0x55c      // x0=plus's address=0x40055c
  4005b8:	f90013a0 	str	x0, [x29, #32]
  4005bc:	f94013a2 	ldr	x2, [x29, #32]      // x2=0x40055c
  4005c0:	528000a1 	mov	w1, #0x5                   	// #5
  4005c4:	52800080 	mov	w0, #0x4                   	// #4
  4005c8:	d63f0040 	blr	x2                  // 0x40055c(4,5)
  4005cc:	b9002fa0 	str	w0, [x29, #44]      // [x29+44]=0x40055c(4,5)
  4005d0:	90000000 	adrp	x0, 400000 <_init-0x3e8>
  4005d4:	911b8000 	add	x0, x0, #0x6e0
  4005d8:	b9402fa1 	ldr	w1, [x29, #44]
  4005dc:	97ffff9d 	bl	400450 <printf@plt> // printf
  4005e0:	b0000080 	adrp	x0, 411000 <__libc_start_main@GLIBC_2.17>
  4005e4:	9100c001 	add	x1, x0, #0x30   // x1=0x411030=machine_code's address
  4005e8:	90000000 	adrp	x0, 400000 <_init-0x3e8>
  4005ec:	911ba000 	add	x0, x0, #0x6e8  // x0="%p\n"
  4005f0:	97ffff98 	bl	400450 <printf@plt> // printf(x0, x1)
  4005f4:	b0000080 	adrp	x0, 411000 <__libc_start_main@GLIBC_2.17>
  4005f8:	9100c000 	add	x0, x0, #0x30   // x0=0x411030=machine_code's address
  4005fc:	f90013a0 	str	x0, [x29, #32]
  400600:	f94013a2 	ldr	x2, [x29, #32]  // x2=0x411030=machine_code's address
  400604:	528000a1 	mov	w1, #0x5                   	// #5
  400608:	52800080 	mov	w0, #0x4                   	// #4
  40060c:	d63f0040 	blr	x2              // 0x411030(4,5)
  400610:	2a0003e1 	mov	w1, w0
  400614:	90000000 	adrp	x0, 400000 <_init-0x3e8>
  400618:	911bc000 	add	x0, x0, #0x6f0
  40061c:	97ffff8d 	bl	400450 <printf@plt>
  400620:	52800000 	mov	w0, #0x0                   	// #0
  400624:	a8c37bfd 	ldp	x29, x30, [sp], #48
  400628:	d65f03c0 	ret
  40062c:	00000000 	.inst	0x00000000 ; undefined


#endif